#ifndef __MATRIZ_ESPARZA_H__
#define __MATRIZ_ESPARZA_H__

#include <iostream>
#include <auxiliares.h>
#include <vector>
#include <matriz.h>
#include <auxiliares.h>
#include <algorithm>

#include <iomanip>
#include <map>
#include <float.h>

using namespace std;

typedef vector<vector<pair<unsigned int, double> > >    vvpid;                  /* Vector de Vector de Pares de (unsigned) Int y Double */
typedef vector<pair<unsigned int, double> >                             vpid;
typedef pair<unsigned int, double>                                              pid;

class matriz_esp
{
        public:
       
                matriz_esp();
                matriz_esp(matriz<tripla_dbl>& m);
               
                double get_elem_m(unsigned int fila, unsigned int columna);             /* Get elem de M */
                double get_elem_mtxm(unsigned int fila, unsigned int columna);  /* Get elem de MtxM */
               
                unsigned int cant_filas_m()             { return _m_filas; };
                unsigned int cant_columnas_m()          { return _m_colum; };
                unsigned int cant_filas_mtxm()          { return _m_colum; };
                unsigned int cant_columnas_mtxm()       { return _m_colum; };
               
                void mostrar_m();
                void mostrar_mtxm();
                void mostrar_mtxm_pf();
                void mostrar_mtxm_pc();
               
                void mostrar_b();
               
                vector<double> mult_mt(vector<double> &v);
               
                vector<double> resolver();
                               
        private:
       
                /** Estructuras **/
               
                unsigned int _m_filas;
                unsigned int _m_colum;
               
                unsigned int _mtxm_filas;
                unsigned int _mtxm_columnas;
               
                unsigned int _filas_original;           // Cantidad de filas de la matriz con la que fue contruida la esparza
                unsigned int _columnas_original;        // Idem columnas
               
                vvpid _m;                       // Matriz M almacenada por filas. Es decir, si haces _m[i] tenes la iesima fila
               
                vvpid _mtxm_pf;         // Matriz MtxM almacenada por filas
                vvpid _mtxm_pc;         // Matriz MtxM almacenada por columnas
       
                vector<double> b;       // Vector termino independiente
                vector<double> x;       // Vector de incognitas
                               
                /** Metodos privados **/               
               
                void _construir_m(matriz<tripla_dbl>& m);
                void _construir_mtxm();
                void _construir_b(matriz<tripla_dbl>& m);
               
                /* Metodos para _m */
               
                double _m_get_elem(unsigned int fila, unsigned int columna);
                bool _m_set_elem(unsigned int fila, unsigned int columna, double valor);                /* Setea un elemento en m */
               
                /* Metodos para _mtxv */
               
                double _mtxm_get_elem_pf(unsigned int fila, unsigned int columna);
                double _mtxm_get_elem_pc(unsigned int fila, unsigned int columna);
               
                bool _mtxm_add_elem(unsigned int fila, unsigned int columna, double valor);
                bool _mtxm_add_elem_pf(unsigned int fila, unsigned int columna, double valor);
                bool _mtxm_add_elem_pc(unsigned int fila, unsigned int columna, double valor);
               
       
                bool _mtxm_set_elem(unsigned int fila, unsigned int columna, double valor);                     // Creo que no se usa (solo la usa _mtxm_del_elem)
                bool _mtxm_set_elem_pf(unsigned int fila, unsigned int columna, double valor);          // Creo que no se usa (solo la usa _mtxm_set_elem)
                bool _mtxm_set_elem_pc(unsigned int fila, unsigned int columna, double valor);          // Creo que no se usa (solo la usa _mtxm_set_elem)
               
                bool _mtxm_del_elem(unsigned int fila, unsigned int columna);                                           // Creo que no se usa
               
                /* Otras funciones */
               
                void _mtxm_triangular();
                void _mtxm_backsust();
                void _mtxm_reestablecer_inv_pf();
               
};

#endif /* __MATRIZ_ESPARZA_H__ */
